home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianEvents.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  40KB  |  1,846 lines

  1. /*ScianEvents.c
  2.   Eric Pepke
  3.   March 8, 1990
  4.   Event stuff for scian
  5. */
  6.  
  7. #include "Scian.h"
  8. #include "ScianTypes.h"
  9. #include "ScianWindows.h"
  10. #include "ScianEvents.h"
  11. #include "ScianGarbageMan.h"
  12. #include "ScianSockets.h"
  13. #include "ScianScripts.h"
  14. #include "ScianColors.h"
  15. #include "ScianIDs.h"
  16. #include "ScianTimers.h"
  17. #include "ScianMainWindow.h"
  18. #include "ScianObjWindows.h"
  19. #include "ScianVisWindows.h"
  20. #include "ScianPreferences.h"
  21. #include "ScianObjFunctions.h"
  22. #include "ScianDialogs.h"
  23. #include "ScianDraw.h"
  24. #include "ScianStyle.h"
  25. #include "ScianLists.h"
  26. #include "ScianObjWindows.h"
  27. #include "ScianFontMappings.h"
  28. #include "ScianMenus.h"
  29.  
  30. long lastAwake = MAXINT;
  31. int settleEvents = 0;            /*Events to settle*/
  32. ObjPtr dropObject = NULLOBJ;        /*Object to drop in window*/
  33. int dropX, dropY;            /*Global coordinates of place to drop*/
  34. #ifdef INTERACTIVE
  35. int curMouse = LEFTMOUSE;        /*Current mouse button down*/
  36. Bool interactiveMoving = false;        /*True iff moving interactively*/
  37. Bool contextHelp = false;        /*Context sensitive help*/
  38. #endif
  39. #ifdef IRISNTSC
  40. Bool NTSCOn = 0;                /*True iff NTSC is on*/
  41. #endif
  42. Bool stereoOn = 0;
  43. long lastGC = 0;            /*Time of last garbage collection*/
  44. #define GCEVERY    ((HEARTBEAT) * 10)    /*One garbage collection per ten seconds*/
  45. #define NAPEVERY ((HEARTBEAT) * 5)    /*Nap after 5 seconds*/
  46. long defaultMonitor;            /*Default monitor*/
  47. Event events[MAXNEVENTS];
  48. int curEvent = 0;            /*Current and last events for queue*/
  49. int lastEvent = 0;            /*Queue empty when they're the same*/
  50. Bool knownUserEvent;            /*There is a user event known*/
  51. ObjPtr drawLaterList;            /*List of things to draw later*/
  52. long interactBegin;            /*Begin time of interaction*/
  53. #define INTERACTDELAY    HEARTBEAT    /*Interaction end after a second*/
  54.  
  55. int lastDialValues[8] =            /*Last values for each dial*/
  56.     {0, 0, 0, 0, 0, 0, 0, 0};
  57.  
  58. #define MAXNTASKS    100        /*Maximum # of tasks*/
  59.  
  60. TaskType doTasks[MAXNTASKS];        /*Tasks to do*/
  61. int tasksLeft = 0;            /*Number of tasks left*/
  62.  
  63. #define MAXNDEFMES    100        /*Maximum # of deferred messages*/
  64.  
  65. int curDef = 0;                /*Current deferred message set*/
  66. WinInfoPtr lastCursorWindow = 0;    /*Last cursor window*/
  67.  
  68. struct
  69.     {
  70.     ObjPtr object;            /*The object to send the message*/
  71.     NameTyp message;        /*The message to send*/
  72.     } defMessages[2][MAXNDEFMES];
  73. int defMesLeft = 0;
  74.  
  75. #ifdef INTERACTIVE
  76. long lastClickTime = 0;            /*The time the last click was done*/
  77. long lastKeyTime = 0;            /*The last time of a keypress*/
  78. int lastClickX, lastClickY;        /*The last click X and Y*/ 
  79. int sentKey = 0;            /*Last key that has been sent*/
  80. WinInfoPtr keyWindow = 0;        /*Window the last key was sent to*/
  81. #endif
  82.  
  83. int running = 1;            /*True iff running*/
  84.  
  85. #ifdef INTERACTIVE
  86. /*Values for mouse switchboard*/
  87. #define MOUSEPRESS    1        /*Select, drag, etc. with mouse*/
  88. #define MOUSEMENU    2        /*Bring up mouse menu*/
  89. #define MOUSEROTATE    3        /*Rotate with the mouse*/
  90.  
  91. /*Mouse switchboard*/
  92. int mouseSwitchboard[3] =
  93.     {
  94.     MOUSEMENU,
  95.     MOUSEROTATE,
  96.     MOUSEPRESS
  97.     };
  98. #endif
  99.  
  100. char *functionKeyNames[FK_N];        /*Names of extra function keys*/
  101.  
  102. #ifdef PROTO
  103. void NeedToDrawFullQuality(ObjPtr object)
  104. #else
  105. void NeedToDrawFullQuality(object)
  106. ObjPtr object;
  107. #endif
  108. /*Requests that an object needs to be drawn in full quality later*/
  109. {
  110.     if (interactiveMoving)
  111.     {
  112.     if (WhichListIndex(drawLaterList, object) < 0)
  113.     {
  114.         PrefixList(drawLaterList, object);
  115.     }
  116.     }
  117.     else
  118.     {
  119.     ImInvalid(object);
  120.     }
  121. }
  122.  
  123. #ifdef PROTO
  124. void DrawInteractive(Bool whether)
  125. #else
  126. void DrawInteractive(whether)
  127. Bool whether;
  128. #endif
  129. /*Sets interactive drawing to whether*/
  130. {
  131.     if (whether)
  132.     {
  133.     /*Mark this point in time as beginning of interaction*/
  134.     struct tms buffer;
  135.  
  136.     interactBegin = times(&buffer);
  137.     }
  138.     else if (whether != interactiveMoving)
  139.     {
  140.     /*Inval everything on drawLaterList before making transition*/
  141.     ThingListPtr runner;
  142.  
  143.     runner = LISTOF(drawLaterList);
  144.     while(runner)
  145.     {
  146.         ImInvalid(runner -> thing);
  147.         runner = runner -> next;
  148.     }
  149.     EmptyList(drawLaterList);
  150.     }
  151.     interactiveMoving = whether;
  152. }
  153.  
  154. void DoTask(task)
  155. TaskType task;
  156. /*Asks the system to do task at its earliest possible convenience*/
  157. {
  158.     doTasks[tasksLeft++] = task;
  159. }
  160.  
  161. #ifdef PROTO
  162. void DeferMessage(ObjPtr object, NameTyp message)
  163. #else
  164. void DeferMessage(object, message)
  165. ObjPtr object;
  166. NameTyp message;
  167. #endif
  168. /*Asks the system to do task at its earliest possible convenience*/
  169. {
  170.     defMessages[curDef][defMesLeft] . object = object;
  171.     defMessages[curDef][defMesLeft] . message = message;
  172.     ++defMesLeft;
  173. }
  174.  
  175. void DeferUniqueMessage(object, message)
  176. ObjPtr object;
  177. int message;
  178. /*Asks the system to do task at its earliest possible convenience*/
  179. {
  180.     int k;
  181.     for (k = 0; k < defMesLeft; ++k)
  182.     {
  183.     if ((defMessages[curDef][k] . object == object) &&
  184.         (defMessages[curDef][k] . message == message))
  185.     {
  186.         return;
  187.     }
  188.     }
  189.  
  190.     defMessages[curDef][defMesLeft] . object = object;
  191.     defMessages[curDef][defMesLeft] . message = message;
  192.     ++defMesLeft;
  193. }
  194.  
  195. void DoUniqueTask(task)
  196. TaskType task;
  197. /*Asks the system to do task at its earliest possible convenience,
  198.   but only if it hasn't already been requested*/
  199. {
  200.     int k;
  201.     for (k = 0; k < tasksLeft; ++k)
  202.     {
  203.     if (doTasks[k] == task)
  204.     {
  205.         return;
  206.     }
  207.     }
  208.     doTasks[tasksLeft++] = task;
  209. }
  210.  
  211. void DoQuit()
  212. /*Asks to quit on the next loop*/
  213. {
  214.     running = 0;
  215. }
  216.  
  217. ObjPtr QuitReply(window, button)
  218. WinInfoPtr window;
  219. int button;
  220. {
  221.     if (button == 0)
  222.     {
  223.     DoQuit();
  224.     }
  225. }
  226.  
  227. void MaybeQuit()
  228. /*Maybe quits on the next loop*/
  229. {
  230.     if (OptionDown())
  231.     {
  232.     DoQuit();
  233.     }
  234.     else
  235.     {
  236.     WinInfoPtr alertWindow;
  237.     alertWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "Do you really want to quit SciAn?",
  238.         QuitReply, 2, "Quit", "Cancel");
  239.     SetVar((ObjPtr) alertWindow, INHIBITLOGGING, ObjTrue);
  240.     }
  241. }
  242.  
  243. #ifdef INTERACTIVE
  244. void QueueDevices()
  245. /*Queues up all the devices that will be used by Scian*/
  246. {
  247.     qdevice(KEYBD);
  248.     qdevice(PADPF1);
  249.     qdevice(F1KEY);
  250.     qdevice(PADPF2);
  251.     qdevice(F2KEY);
  252.     qdevice(PADPF3);
  253.     qdevice(F3KEY);
  254.     qdevice(PADPF4);
  255.     qdevice(F4KEY);
  256.     qdevice(F5KEY);
  257.     qdevice(F6KEY);
  258.     qdevice(F7KEY);
  259.     qdevice(F8KEY);
  260.     qdevice(F9KEY);
  261.     qdevice(F10KEY);
  262.     qdevice(F11KEY);
  263.     qdevice(F12KEY);
  264.     qdevice(MOUSE1);
  265.     qdevice(MOUSE2);
  266.     qdevice(MOUSE3);
  267.     qdevice(UPARROWKEY);
  268.     qdevice(DOWNARROWKEY);
  269.     qdevice(LEFTARROWKEY);
  270.     qdevice(RIGHTARROWKEY);
  271.     qdevice(WINFREEZE);
  272.     qdevice(WINTHAW);
  273. #ifdef DIALBOX
  274.     qdevice(DIAL0);
  275.     qdevice(DIAL1);
  276.     qdevice(DIAL2);
  277.     qdevice(DIAL3);
  278.     qdevice(DIAL4);
  279.     qdevice(DIAL5);
  280.     qdevice(DIAL6);
  281.     qdevice(DIAL7);
  282. #endif
  283. #ifdef DEPTHCHANGE
  284.     qdevice(DEPTHCHANGE);
  285. #endif
  286. #ifdef IRIS
  287. #ifdef WINQUIT
  288.     qdevice(WINQUIT);
  289. #endif
  290.     qdevice(WINSHUT);
  291.     qdevice(BUT157);
  292. #endif
  293. }
  294.  
  295. void UnqueueDevices()
  296. /*Unqueues all the devices*/
  297. {
  298. #ifdef DIALBOX
  299.     unqdevice(DIAL0);
  300.     unqdevice(DIAL1);
  301.     unqdevice(DIAL2);
  302.     unqdevice(DIAL3);
  303.     unqdevice(DIAL4);
  304.     unqdevice(DIAL5);
  305.     unqdevice(DIAL6);
  306.     unqdevice(DIAL7);
  307. #endif
  308. #ifdef DEPTHCHANGE
  309.     unqdevice(DEPTHCHANGE);
  310. #endif
  311.     unqdevice(WINFREEZE);
  312.     unqdevice(WINTHAW);
  313.     unqdevice(KEYBD);
  314.     unqdevice(PADPF1);
  315.     unqdevice(F1KEY);
  316.     unqdevice(PADPF2);
  317.     unqdevice(F2KEY);
  318.     unqdevice(PADPF3);
  319.     unqdevice(F3KEY);
  320.     unqdevice(PADPF4);
  321.     unqdevice(F4KEY);
  322.     unqdevice(F5KEY);
  323.     unqdevice(F6KEY);
  324.     unqdevice(F7KEY);
  325.     unqdevice(F8KEY);
  326.     unqdevice(F9KEY);
  327.     unqdevice(F10KEY);
  328.     unqdevice(F11KEY);
  329.     unqdevice(F12KEY);
  330.     unqdevice(MOUSE1);
  331.     unqdevice(MOUSE2);
  332.     unqdevice(MOUSE3);
  333.     unqdevice(UPARROWKEY);
  334.     unqdevice(DOWNARROWKEY);
  335.     unqdevice(LEFTARROWKEY);
  336.     unqdevice(RIGHTARROWKEY);
  337. #ifdef IRIS
  338. #ifdef WINQUIT
  339.     qdevice(WINQUIT);
  340. #endif
  341.     unqdevice(WINSHUT);
  342.     unqdevice(BUT157);
  343. #endif
  344. }
  345. #endif
  346.  
  347. void LongOperation()
  348. /*Signals the user that a long operation is about to occur
  349.   This version sets to the watchcursor*/
  350. {
  351.     MySetCursor(WATCHCURSOR);
  352. }
  353.  
  354. void EndLongOperation()
  355. /*Ends a long operation*/
  356. {
  357.     if (curCursor == WATCHCURSOR)
  358.     {
  359.     MySetCursor(0);
  360.     }
  361. }
  362.  
  363. #ifdef INTERACTIVE
  364. void SetContextSensitiveHelp()
  365. /*Sets up the system so that the next press click is a help*/
  366. {
  367.     MySetCursor(QUESTIONCURSOR);
  368.     contextHelp = true;
  369. }
  370. #endif
  371.  
  372. #ifdef INTERACTIVE
  373. #ifdef PROTO
  374. void KeyDown(int theKey, long flags)
  375. #else
  376. void KeyDown(theKey, flags)
  377. int theKey;
  378. long flags;
  379. #endif
  380. /*Does a keyDown for theKey with flags.*/
  381. {
  382.     WinInfoPtr window;
  383.  
  384.     window = inputWindow;
  385.     if (!inputWindow)
  386.     {
  387.     /*No focus; return*/
  388.     return;
  389.     }
  390.     SelWindow(inputWindow);
  391.  
  392.     if (!selWinInfo)
  393.     {
  394.     /*Pathological case.  Return.*/
  395.     return;
  396.     }
  397.  
  398.     if (DoFunctionKey(theKey, flags))
  399.     {
  400.     }
  401.     else
  402.     {
  403.     FuncTyp actionMethod;        /*The method to call for the action*/
  404.  
  405.     /*See if it's one of the funny characters*/
  406.     switch (theKey)
  407.     {
  408.     case CONTROL('C'):
  409. #ifdef CH_COPYRIGHT
  410.         theKey = CH_COPYRIGHT;
  411. #endif
  412.         break;
  413.     case CONTROL('X'):
  414. #ifdef CH_CROSS
  415.         theKey = CH_CROSS;
  416. #endif
  417.         break;
  418.     case CONTROL('D'):
  419. #ifdef CH_DOT
  420.         theKey = CH_DOT;
  421. #endif
  422.         break;
  423.     case CONTROL('R'):
  424. #ifdef CH_REGISTERED
  425.         theKey = CH_REGISTERED;
  426. #endif
  427.         break;
  428.    }
  429.  
  430.     actionMethod = GetMethod((ObjPtr) selWinInfo, KEYDOWN);
  431.     if (actionMethod)
  432.     {
  433.         /*There's a key down routine.  Call it.*/
  434.         DrawInteractive(true);
  435.         if (theKey == '\r')
  436.         {
  437.         /*Kludge to get it to flush stuff before enter key*/
  438.         FlushKeystrokes();
  439.         }
  440.         (*actionMethod)(selWinInfo, theKey, flags);
  441.     }
  442.     }
  443. }
  444. #endif
  445.  
  446. void FlushKeystrokes()
  447. /*Flushes the keystrokes to an object that takes keystrokes*/
  448. {
  449. #ifdef INTERACTIVE
  450.     if (sentKey && IsValidWindow(keyWindow))
  451.     {
  452.     WinInfoPtr tempInput;
  453.     Screencoord l, r, b, t; 
  454.     WinInfoPtr oldWindow;
  455.  
  456.     oldWindow = selWinInfo;
  457.  
  458.     tempInput = inputWindow;
  459.     inputWindow = keyWindow;
  460.     sentKey = 0;
  461.     KeyDown(0, 0);
  462.     inputWindow = tempInput;
  463.  
  464.     if (oldWindow)
  465.     {
  466.         SelWindow(oldWindow);
  467.     }
  468.     }
  469. #endif
  470. }
  471.  
  472. Bool Mouse(x, y)
  473. int *x, *y;
  474. /*Returns in x and y the current mouse position in local coordinates*/
  475. {
  476. #ifdef INTERACTIVE
  477.     int ox, oy;
  478.  
  479.     UD();
  480.  
  481.     CurOffset(&ox, &oy);
  482.  
  483.     *x = getvaluator(MOUSEX) - ox;
  484.     *y = getvaluator(MOUSEY) - oy;
  485.  
  486.     switch (curMouse)
  487.     {
  488.     case MB_LEFT:
  489.         return getbutton(MOUSE1);
  490.     case MB_MIDDLE:
  491.         return getbutton(MOUSE2);
  492.     case MB_RIGHT:
  493.         return getbutton(MOUSE3);
  494.     }
  495. #else
  496.     return false;
  497. #endif
  498. }
  499.  
  500. #ifdef INTERACTIVE
  501. static ObjPtr AbortScript(owner, button)
  502. ObjPtr owner;
  503. int button;
  504. /*Callback routine to abort a script*/
  505. {
  506.     if (button)
  507.     {
  508.     /*Continue*/
  509.     runningScript = true;
  510.     }
  511.     else
  512.     {
  513.     /*Real abort*/
  514.     EndScript();
  515.     }
  516. }
  517.  
  518. void AbortScriptAlert()
  519. /*Puts up an alert to abort the script*/
  520. {
  521.     WinInfoPtr errWindow;
  522.     MySetCursor(0);
  523.     runningScript = false;
  524.     errWindow = AlertUser(UICAUTIONALERT, (WinInfoPtr) 0,
  525.     "SciAn is currently running a script.  Would you like to abort the \
  526. script or continue running it?",
  527.         AbortScript, 2, "Abort", "Continue");
  528.     SetVar((ObjPtr) errWindow, HELPSTRING,
  529.         NewString("SciAn expects no user interaction while running a script.  \
  530. This is because changing the state of the windows of SciAn while running a \
  531. script can cause the script to generate an error.  It is best either to \
  532. abort the script or continue and not interfere with it.  However, if you are really \
  533. sure you know what you are doing, you can interact with SciAn now and press the \
  534. Continue button later.  This is not recommended for the inexperienced."));
  535.     SetVar((ObjPtr) errWindow, INHIBITLOGGING, ObjTrue);
  536. }
  537.  
  538. #ifdef PROTO
  539. void MouseDown(int whichButton, int x, int y, long flags)
  540. #else
  541. void MouseDown(whichButton, x, y, flags)
  542. int whichButton;
  543. int x, y;
  544. long flags;
  545. #endif
  546. /*Does a mouseDown.
  547.   whichButton should be MB_LEFT, MB_MIDDLE, or MB_RIGHT.
  548.   x and y are in global coordinates.*/
  549. {
  550.     int action;                /*The action to do*/
  551.     FuncTyp actionMethod;        /*The method to call for the action*/
  552.     int ox, oy;
  553.     WinInfoPtr mouseWindow;
  554.  
  555.     curMouse = whichButton;
  556.  
  557.     mouseWindow = WhichWindow(x, y);
  558.     if (!mouseWindow && !(IsValidWindow(mouseWindow)))
  559.     {
  560.     /*No focus; return*/
  561.     return;
  562.     }
  563.  
  564.     if (Equal(mouseWindow, GetVar(objClass, MOUSEWINDOW)))
  565.     {
  566.     }
  567.     else
  568.     {
  569.     SetVar(objClass, MOUSEWINDOW, (ObjPtr) mouseWindow);
  570.     }
  571.     SelWindow(mouseWindow);
  572.    
  573.     if (!selWinInfo)
  574.     {
  575.     /*Pathological case.  Return.*/
  576.     return;
  577.     }
  578.  
  579.     /*Determine the action based on the mouse switchboard*/
  580.     switch(whichButton)
  581.     {
  582.     case MB_LEFT:
  583.         action = mouseSwitchboard[0];
  584.         break;
  585.     case MB_MIDDLE:
  586.         action = mouseSwitchboard[1];
  587.         break;
  588.     case MB_RIGHT:
  589.         action = mouseSwitchboard[2];
  590.         break;
  591.     }
  592.  
  593.     /*Do the action*/
  594.     switch(action)
  595.     {
  596.     case MOUSEROTATE:
  597.         GetWindowOrigin(&ox, &oy);
  598.         x -= ox;
  599.         y -= oy;
  600.  
  601.         actionMethod = GetMethod((ObjPtr) selWinInfo, PRESS);
  602.         if (actionMethod)
  603.         {
  604.         DrawInteractive(true);
  605.  
  606.         /*There's a press routine.  Call it.*/
  607.         if (contextHelp)
  608.         {
  609.             (*actionMethod)(selWinInfo, x, y, T_HELP | flags);
  610.             contextHelp = false;
  611.             MySetCursor(0);
  612.         }    
  613.         else
  614.         {
  615.             (*actionMethod)(selWinInfo, x, y, T_ROTATE | flags);
  616.         }
  617.         DrawInteractive(false);
  618.         }
  619.         break;
  620.     case MOUSEPRESS:
  621.         GetWindowOrigin(&ox, &oy);
  622.         x -= ox;
  623.         y -= oy;
  624.  
  625.         if (dragBuffer)
  626.         {
  627.         dropX = getvaluator(MOUSEX);
  628.         dropY = getvaluator(MOUSEY);
  629.         MySetCursor(0);
  630.         }
  631.         actionMethod = GetMethod((ObjPtr) selWinInfo, PRESS);
  632.         if (actionMethod)
  633.         {
  634.         DrawInteractive(true);
  635.  
  636.         /*There's a press routine.  Call it.*/
  637.         if (contextHelp)
  638.         {
  639.             (*actionMethod)(selWinInfo, x, y, T_HELP | flags);
  640.             contextHelp = false;
  641.             MySetCursor(0);
  642.         }    
  643.         else
  644.         {
  645.             (*actionMethod)(selWinInfo, x, y, T_PRESS | flags);
  646.         }
  647.         DrawInteractive(false);
  648.         }
  649.         if (dragBuffer)
  650.         {
  651.         DeleteThing(dragBuffer);
  652.         dragBuffer = 0;
  653.         }
  654.  
  655.         break;
  656.     case MOUSEMENU:
  657.         /*Do the main menu*/
  658.         DoMenu(mainMenu, x, y);
  659.         break;
  660.     }
  661. }
  662. #endif
  663.  
  664. #ifdef IRISNTSC
  665. void SetNTSC()
  666. /*Sets to NTSC mode*/
  667. {
  668.     NTSCOn = true;
  669. #ifdef GRAPHICS
  670.     setmonitor(NTSC);
  671. #ifdef GL4D
  672.     setvideo(CG_MODE, CG2_M_MODE2);
  673.     setvideo(DE_R1, DER1_G_170);
  674. #endif
  675. #endif
  676. }
  677.  
  678. void SetStereo()
  679. /*Sets to stereo*/
  680. {
  681.     stereoOn = true;
  682.  
  683. #ifdef STR_RECT
  684.     setmonitor(STR_RECT);
  685. #endif
  686. }
  687.  
  688. void Set60()
  689. /*Sets to 60 Hz mode*/
  690. {
  691.     NTSCOn = false;
  692.     stereoOn = false;
  693. #ifdef GRAPHICS
  694.     setmonitor(defaultMonitor);
  695. #endif
  696. }
  697.  
  698. void ToggleNTSC()
  699. /*Toggles in and out of NTSC mode*/
  700. {
  701.     NTSCOn = NTSCOn ? false : true;
  702. #ifdef GRAPHICS
  703.     setmonitor(NTSCOn ? NTSC : defaultMonitor);
  704. #ifdef GL4D
  705.     if (NTSCOn)
  706.     {
  707.     setvideo(CG_MODE, CG2_M_MODE2);
  708.     setvideo(DE_R1, DER1_G_170);
  709.     }
  710. #endif
  711. #endif
  712. }
  713.  
  714. void ToggleStereo()
  715. /*Toggles in and out of stereo mode*/
  716. {
  717.     stereoOn = stereoOn ? false : true;
  718. #ifdef GRAPHICS
  719. #ifdef STR_RECT
  720.     setmonitor(stereoOn ? STR_RECT : defaultMonitor);
  721. #endif
  722. #endif
  723. }
  724.  
  725. #endif
  726.  
  727. Bool AltDown()
  728. /*Returns true iff the alt key is down*/
  729. {
  730. #ifdef INTERACTIVE
  731.     return (getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY)) ? true : false;
  732. #else
  733.     return false;
  734. #endif
  735. }
  736.  
  737. Bool ShiftDown()
  738. /*Returns true iff the shift key is down*/
  739. {
  740. #ifdef INTERACTIVE
  741.     return (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY)) ? true : false;
  742. #else
  743.     return false;
  744. #endif
  745. }
  746.  
  747. Bool OptionDown()
  748. /*Returns true iff the option key is down*/
  749. {
  750. #ifdef INTERACTIVE
  751.     return (getbutton(LEFTCTRLKEY) || getbutton(RIGHTCTRLKEY) ||
  752.         getbutton(CAPSLOCKKEY)) ? true : false;
  753. #else
  754.     return false;
  755. #endif
  756. }
  757.  
  758. Bool UserEvent()
  759. /*Determine if there is a user event (mouse down or key down or close
  760.   window) in the queue*/
  761. {
  762.     int k;
  763.  
  764.     if (knownUserEvent)
  765.     {
  766.     return true;
  767.     }
  768.  
  769. #ifndef SIGNALS
  770.     NewEvents();
  771. #endif
  772.  
  773.     k = curEvent;
  774.     while (k != lastEvent)
  775.     {
  776.     k = (k + 1) % MAXNEVENTS;
  777.     if (ISUSEREVENT(events[k] . type))
  778.     {
  779.         knownUserEvent = true;
  780.         return true;
  781.     }
  782.     }
  783.     return false;
  784. }
  785.  
  786. #ifdef PROTO
  787. void PostEvent(Event *event)
  788. #else
  789. void PostEvent(event)
  790. Event *event;
  791. #endif
  792. /*Posts an event just like event, except for time*/
  793. {
  794.     int k;
  795.     char *a, *b;
  796.     struct tms buffer;
  797.  
  798.     lastEvent = (lastEvent + 1) % MAXNEVENTS;
  799.  
  800.     a = (char *) event;
  801.     b = (char *) &(events[lastEvent]);
  802.  
  803.     for (k = 0; k < sizeof(Event); ++k)
  804.     {
  805.     b[k] = a[k];
  806.     }
  807.     events[lastEvent] . time = times(&buffer);
  808.     if (ISUSEREVENT(event -> type))
  809.     {
  810.     knownUserEvent = true;
  811.     }
  812. }
  813.  
  814. void NewEvents()
  815. /*Get all new events and deposit them in the event queue.  Do this every once
  816.   in a while.*/
  817. {
  818. #ifdef INTERACTIVE
  819.     /*Look for an event*/
  820.  
  821.     while (qtest())
  822.     {
  823.         long whichDevice;
  824.         short theData;
  825.     WinInfoPtr window;
  826.     struct tms buffer;
  827.  
  828.         whichDevice = qread(&theData);
  829.     lastEvent = (lastEvent + 1) % MAXNEVENTS;
  830.  
  831.     events[lastEvent] . type = ET_UNKNOWN;
  832.     events[lastEvent] . time = times(&buffer);
  833.     events[lastEvent] . flags = 0;
  834.     /*Determine if the modifier keys are held down*/
  835.     if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
  836.     {
  837.         events[lastEvent] . flags |= F_SHIFTDOWN;
  838.     }
  839.     if (getbutton(LEFTCTRLKEY) || getbutton(RIGHTCTRLKEY) || getbutton(CAPSLOCKKEY))
  840.     {
  841.         events[lastEvent] . flags |= F_OPTIONDOWN;
  842.     }
  843.     if (getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY))
  844.     {
  845.         events[lastEvent] . flags |= F_OPTIONDOWN;
  846.     }
  847.  
  848.         switch (whichDevice)
  849.         {
  850.         case INPUTCHANGE:
  851.         if (theData && (window = GetWinInfo(theData)))
  852.         {
  853.             events[lastEvent] . type = ET_SET_WINDOW;
  854.             events[lastEvent] . data . window = window;
  855.         }
  856.         break;
  857. #ifdef DEPTHCHANGE
  858.         case DEPTHCHANGE:
  859.         if (theData && (window = GetWinInfo(theData)))
  860.         {
  861.             events[lastEvent] . type = ET_DEPTHCHANGE_WINDOW;
  862.             events[lastEvent] . data . window = window;
  863.         }
  864.         break;
  865. #endif
  866.         case WINFREEZE:
  867.         if (theData && (window = GetWinInfo(theData)))
  868.         {
  869.             events[lastEvent] . type = ET_ICONIFY_WINDOW;
  870.             events[lastEvent] . data . window = window;
  871.         }
  872.         break;
  873.         case WINTHAW:
  874.         if (theData && (window = GetWinInfo(theData)))
  875.         {
  876.             events[lastEvent] . type = ET_DEICONIFY_WINDOW;
  877.             events[lastEvent] . data . window = window;
  878.         }
  879.         break;
  880.              case KEYBD:
  881.         if (events[lastEvent] . time - lastKeyTime < CLICK2TIME)
  882.         { 
  883.             events[lastEvent] . flags |= F_DOUBLECLICK; 
  884.             lastKeyTime = events[lastEvent] . time;
  885.         }
  886.         events[lastEvent] . type = ET_KEY_DOWN;
  887.         events[lastEvent] . data . key = theData;
  888.         break;
  889.         case MOUSE1:
  890.         if (theData)
  891.         {
  892.             int newX, newY;
  893.  
  894.             /*Determine if this is potentially a double click*/
  895.             newX = getvaluator(MOUSEX);
  896.             newY = getvaluator(MOUSEY);
  897.             if (events[lastEvent] . time - lastClickTime < CLICK2TIME &&
  898.             ABS(newX - lastClickX) < CLICK2DIST &&
  899.             ABS(newY - lastClickY) < CLICK2DIST)
  900.             {
  901.             events[lastEvent] . flags |= F_DOUBLECLICK;
  902.             }
  903.  
  904.             lastClickX = newX;
  905.             lastClickY = newY;
  906.  
  907.             events[lastEvent] . type = ET_MOUSE_DOWN;
  908.         }
  909.         else
  910.         {
  911.             events[lastEvent] . type = ET_MOUSE_UP;
  912.             lastClickTime = events[lastEvent] . time;
  913.         }
  914.         events[lastEvent] . data . mouse . x = getvaluator(MOUSEX);
  915.         events[lastEvent] . data . mouse . y = getvaluator(MOUSEY);
  916.          events[lastEvent] . data . mouse . mouseButton = MB_LEFT;
  917.         break;
  918.         case MOUSE2:
  919.         if (theData)
  920.         {
  921.             int newX, newY;
  922.  
  923.             /*Determine if this is potentially a double click*/
  924.             newX = getvaluator(MOUSEX);
  925.             newY = getvaluator(MOUSEY);
  926.             if (events[lastEvent] . time - lastClickTime < CLICK2TIME &&
  927.             ABS(newX - lastClickX) < CLICK2DIST &&
  928.             ABS(newY - lastClickY) < CLICK2DIST)
  929.             {
  930.             events[lastEvent] . flags |= F_DOUBLECLICK;
  931.             }
  932.  
  933.             lastClickX = newX;
  934.             lastClickY = newY;
  935.  
  936.             events[lastEvent] . type = ET_MOUSE_DOWN;
  937.         }
  938.         else
  939.         {
  940.             events[lastEvent] . type = ET_MOUSE_UP;
  941.             lastClickTime = events[lastEvent] . time;
  942.         }
  943.         events[lastEvent] . data . mouse . x = getvaluator(MOUSEX);
  944.         events[lastEvent] . data . mouse . y = getvaluator(MOUSEY);
  945.          events[lastEvent] . data . mouse . mouseButton = MB_MIDDLE;
  946.         break;
  947.         case MOUSE3:
  948.         if (theData)
  949.         {
  950.             int newX, newY;
  951.  
  952.             /*Determine if this is potentially a double click*/
  953.             newX = getvaluator(MOUSEX);
  954.             newY = getvaluator(MOUSEY);
  955.             if (events[lastEvent] . time - lastClickTime < CLICK2TIME &&
  956.             ABS(newX - lastClickX) < CLICK2DIST &&
  957.             ABS(newY - lastClickY) < CLICK2DIST)
  958.             {
  959.             events[lastEvent] . flags |= F_DOUBLECLICK;
  960.             }
  961.  
  962.             lastClickX = newX;
  963.             lastClickY = newY;
  964.  
  965.             events[lastEvent] . type = ET_MOUSE_DOWN;
  966.         }
  967.         else
  968.         {
  969.             events[lastEvent] . type = ET_MOUSE_UP;
  970.             lastClickTime = events[lastEvent] . time;
  971.         }
  972.         events[lastEvent] . data . mouse . x = getvaluator(MOUSEX);
  973.         events[lastEvent] . data . mouse . y = getvaluator(MOUSEY);
  974.          events[lastEvent] . data . mouse . mouseButton = MB_RIGHT;
  975.         break;
  976.         case REDRAW:
  977.         if (theData && (window = GetWinInfo(theData)))
  978.         {
  979.             events[lastEvent] . type = ET_RESHAPE_WINDOW;
  980.             events[lastEvent] . data . window = window;
  981.         }
  982.         break;
  983.         case PIECECHANGE:
  984.         if (theData && (window = GetWinInfo(theData)))
  985.         {
  986.             events[lastEvent] . type = ET_RESHAPE_WINDOW;
  987.             events[lastEvent] . data . window = window;
  988.         }
  989.         break;
  990.         case UPARROWKEY:
  991.         if (theData)
  992.         {
  993.             events[lastEvent] . type = ET_KEY_DOWN;
  994.         events[lastEvent] . data . key = FK_UP_ARROW;
  995.         }
  996.         break;
  997.         case DOWNARROWKEY:
  998.         if (theData)
  999.         {
  1000.             events[lastEvent] . type = ET_KEY_DOWN;
  1001.         events[lastEvent] . data . key = FK_DOWN_ARROW;
  1002.         }
  1003.         break;
  1004.         case LEFTARROWKEY:
  1005.         if (theData)
  1006.         {
  1007.             events[lastEvent] . type = ET_KEY_DOWN;
  1008.         events[lastEvent] . data . key = FK_LEFT_ARROW;
  1009.         }
  1010.         break;
  1011.         case RIGHTARROWKEY:
  1012.         if (theData)
  1013.         {
  1014.             events[lastEvent] . type = ET_KEY_DOWN;
  1015.         events[lastEvent] . data . key = FK_RIGHT_ARROW;
  1016.         }
  1017.         break;
  1018.         case BUT157:
  1019.         if (theData)
  1020.         {
  1021.             events[lastEvent] . type = ET_KEY_DOWN;
  1022.             events[lastEvent] . data . key = FK_PRINT_SCREEN;
  1023.         }
  1024.         break;
  1025.         case PADPF1:
  1026.         case F1KEY:
  1027.         if (theData)
  1028.         {
  1029.             events[lastEvent] . type = ET_KEY_DOWN;
  1030.         events[lastEvent] . data . key = FK_1;
  1031.         }
  1032.         break;
  1033.         case PADPF2:
  1034.         case F2KEY:
  1035.         if (theData)
  1036.         {
  1037.             events[lastEvent] . type = ET_KEY_DOWN;
  1038.         events[lastEvent] . data . key = FK_2;
  1039.         }
  1040.         break;
  1041.         case PADPF3:
  1042.         case F3KEY:
  1043.         if (theData)
  1044.         {
  1045.             events[lastEvent] . type = ET_KEY_DOWN;
  1046.         events[lastEvent] . data . key = FK_3;
  1047.         }
  1048.         break;
  1049.         case PADPF4:
  1050.         case F4KEY:
  1051.         if (theData)
  1052.         {
  1053.             events[lastEvent] . type = ET_KEY_DOWN;
  1054.         events[lastEvent] . data . key = FK_4;
  1055.         }
  1056.         break;
  1057.         case F5KEY:
  1058.         if (theData)
  1059.         {
  1060.             events[lastEvent] . type = ET_KEY_DOWN;
  1061.             events[lastEvent] . data . key = FK_5;
  1062.         }
  1063.         break;
  1064.         case F6KEY:
  1065.         if (theData)
  1066.         {
  1067.             events[lastEvent] . type = ET_KEY_DOWN;
  1068.             events[lastEvent] . data . key = FK_6;
  1069.         }
  1070.         break;
  1071.         case F7KEY:
  1072.         if (theData)
  1073.         {
  1074.             events[lastEvent] . type = ET_KEY_DOWN;
  1075.             events[lastEvent] . data . key = FK_7;
  1076.         }
  1077.         break;
  1078.         case F8KEY:
  1079.         if (theData)
  1080.         {
  1081.             events[lastEvent] . type = ET_KEY_DOWN;
  1082.             events[lastEvent] . data . key = FK_8;
  1083.         }
  1084.         break;
  1085.         case F9KEY:
  1086.         if (theData)
  1087.         {
  1088.             events[lastEvent] . type = ET_KEY_DOWN;
  1089.             events[lastEvent] . data . key = FK_9;
  1090.         }
  1091.         break;
  1092.         case F10KEY:
  1093.         if (theData)
  1094.         {
  1095.             events[lastEvent] . type = ET_KEY_DOWN;
  1096.             events[lastEvent] . data . key = FK_10;
  1097.         }
  1098.         break;
  1099.         case F11KEY:
  1100.         if (theData)
  1101.         {
  1102.             events[lastEvent] . type = ET_KEY_DOWN;
  1103.             events[lastEvent] . data . key = FK_11;
  1104.         }
  1105.         break;
  1106.         case F12KEY:
  1107.         if (theData)
  1108.         {
  1109.             events[lastEvent] . type = ET_KEY_DOWN;
  1110.             events[lastEvent] . data . key = FK_12;
  1111.         }
  1112.         break;
  1113. #ifdef IRIS
  1114.         case WINSHUT:
  1115.         if (theData && (window = GetWinInfo(theData)))
  1116.         {
  1117.             events[lastEvent] . type = ET_CLOSE_WINDOW;
  1118.             events[lastEvent] . data . window = window;
  1119.         }
  1120.         break;
  1121. #ifdef WINQUIT
  1122.         case WINQUIT:
  1123.         if (theData)
  1124.         {
  1125.             events[lastEvent] . type = ET_QUIT;
  1126.             events[lastEvent] . data . window = 0;
  1127.         }
  1128.         break;
  1129. #endif
  1130. #ifdef DIALBOX
  1131.         case DIAL0:
  1132.         if (theData)
  1133.         {
  1134.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1135.             events[lastEvent] . data . dial . whichDial = 0;
  1136.             events[lastEvent] . data . dial . delta = theData - lastDialValues[0];
  1137.             if (theData > 20000 || theData < -20000)
  1138.             {
  1139.             setvaluator(DIAL0, 0, -32767, 32767);
  1140.             lastDialValues[0] = 0;
  1141.             }
  1142.             else
  1143.             {
  1144.             lastDialValues[0] = theData;
  1145.             }
  1146.         }
  1147.         break;
  1148.         case DIAL1:
  1149.         if (theData)
  1150.         {
  1151.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1152.             events[lastEvent] . data . dial . whichDial = 1;
  1153.             events[lastEvent] . data . dial . delta = theData - lastDialValues[1];
  1154.             if (theData > 20000 || theData < -20000)
  1155.             {
  1156.             setvaluator(DIAL1, 0, -32767, 32767);
  1157.             lastDialValues[1] = 0;
  1158.             }
  1159.             else
  1160.             {
  1161.             lastDialValues[1] = theData;
  1162.             }
  1163.         }
  1164.         break;
  1165.         case DIAL2:
  1166.         if (theData)
  1167.         {
  1168.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1169.             events[lastEvent] . data . dial . whichDial = 2;
  1170.             events[lastEvent] . data . dial . delta = theData - lastDialValues[2];
  1171.             if (theData > 20000 || theData < -20000)
  1172.             {
  1173.             setvaluator(DIAL2, 0, -32767, 32767);
  1174.             lastDialValues[2] = 0;
  1175.             }
  1176.             else
  1177.             {
  1178.             lastDialValues[2] = theData;
  1179.             }
  1180.         }
  1181.         break;
  1182.         case DIAL3:
  1183.         if (theData)
  1184.         {
  1185.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1186.             events[lastEvent] . data . dial . whichDial = 3;
  1187.             events[lastEvent] . data . dial . delta = theData - lastDialValues[3];
  1188.             if (theData > 20000 || theData < -20000)
  1189.             {
  1190.             setvaluator(DIAL3, 0, -32767, 32767);
  1191.             lastDialValues[3] = 0;
  1192.             }
  1193.             else
  1194.             {
  1195.             lastDialValues[3] = theData;
  1196.             }
  1197.         }
  1198.         break;
  1199.         case DIAL4:
  1200.         if (theData)
  1201.         {
  1202.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1203.             events[lastEvent] . data . dial . whichDial = 4;
  1204.             events[lastEvent] . data . dial . delta = theData - lastDialValues[4];
  1205.             if (theData > 20000 || theData < -20000)
  1206.             {
  1207.             setvaluator(DIAL4, 0, -32767, 32767);
  1208.             lastDialValues[4] = 0;
  1209.             }
  1210.             else
  1211.             {
  1212.             lastDialValues[4] = theData;
  1213.             }
  1214.         }
  1215.         break;
  1216.         case DIAL5:
  1217.         if (theData)
  1218.         {
  1219.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1220.             events[lastEvent] . data . dial . whichDial = 5;
  1221.             events[lastEvent] . data . dial . delta = theData - lastDialValues[5];
  1222.             if (theData > 20000 || theData < -20000)
  1223.             {
  1224.             setvaluator(DIAL5, 0, -32767, 32767);
  1225.             lastDialValues[5] = 0;
  1226.             }
  1227.             else
  1228.             {
  1229.             lastDialValues[5] = theData;
  1230.             }
  1231.         }
  1232.         break;
  1233.         case DIAL6:
  1234.         if (theData)
  1235.         {
  1236.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1237.             events[lastEvent] . data . dial . whichDial = 6;
  1238.             events[lastEvent] . data . dial . delta = theData - lastDialValues[6];
  1239.             if (theData > 20000 || theData < -20000)
  1240.             {
  1241.             setvaluator(DIAL6, 0, -32767, 32767);
  1242.             lastDialValues[6] = 0;
  1243.             }
  1244.             else
  1245.             {
  1246.             lastDialValues[6] = theData;
  1247.             }
  1248.         }
  1249.         break;
  1250.         case DIAL7:
  1251.         if (theData)
  1252.         {
  1253.             events[lastEvent] . type = ET_ROTATE_DIAL;
  1254.             events[lastEvent] . data . dial . whichDial = 7;
  1255.             events[lastEvent] . data . dial . delta = theData - lastDialValues[7];
  1256.             if (theData > 20000 || theData < -20000)
  1257.             {
  1258.             setvaluator(DIAL7, 0, -32767, 32767);
  1259.             lastDialValues[7] = 0;
  1260.             }
  1261.             else
  1262.             {
  1263.             lastDialValues[7] = theData;
  1264.             }
  1265.         }
  1266.         break;
  1267. #endif
  1268.  
  1269. #endif
  1270.     }
  1271.     }
  1272. #endif
  1273. }
  1274.  
  1275. #ifdef PROTO
  1276. void RotateDial(WinInfoPtr win, int whichDial, int iDelta, long flags)
  1277. #else
  1278. void RotateDial(win, whichDial, iDelta, flags)
  1279. WinInfoPtr win;
  1280. int whichDial;
  1281. int iDelta;
  1282. long flags;
  1283. #endif
  1284. /*Rotates dial whichDial by an amount iDelta within win*/
  1285. {
  1286.     real delta;
  1287.     FuncTyp method;
  1288.  
  1289.     delta = (flags & F_CONSTRAIN) ? iDelta * 0.1 : iDelta;
  1290.  
  1291.     method = GetMethod((ObjPtr) win, TURNDIAL);
  1292.     if (method)
  1293.     {
  1294.     DrawInteractive(true);
  1295.     (*method)((ObjPtr) win, whichDial, delta, T_ROTATE | flags);
  1296.     }
  1297. }
  1298.  
  1299. #ifdef PROTO
  1300. Bool OneEvent(Bool processInput)
  1301. #else
  1302. Bool OneEvent(processInput)
  1303. Bool processInput;
  1304. #endif
  1305. /*Gets and processes one event.  if processInput is true, process input*/
  1306. {
  1307.     Bool readFromScript = true;
  1308.     Bool doNap;
  1309.     int k;
  1310.  
  1311.     if (logging)
  1312.     {
  1313.     InhibitLogging(true);
  1314.     }
  1315.     /*Do the messages remaining*/
  1316.     if (defMesLeft)
  1317.     {
  1318.     int which, defLeft;
  1319.     defLeft = defMesLeft;
  1320.     which = curDef;
  1321.     curDef = curDef ? 0 : 1;
  1322.     defMesLeft = 0;
  1323.     for (k = 0; k < defLeft; ++k)
  1324.     {
  1325.         FuncTyp method;
  1326.         method = GetMethod(defMessages[which][k] . object, defMessages[which][k] . message);
  1327.         if (method)
  1328.         {
  1329.         (*method)(defMessages[which][k] . object);
  1330.         }
  1331.     }
  1332.     }
  1333.     if (logging)
  1334.     {
  1335.     InhibitLogging(false);
  1336.     }
  1337.     
  1338.     /*Do tasks that are waiting*/
  1339.     if (tasksLeft)
  1340.     {
  1341.     for (k = 0; k < tasksLeft; ++k)
  1342.     {
  1343.         (*(doTasks[k]))();
  1344.     }
  1345.     tasksLeft = 0;
  1346.     }
  1347.  
  1348. #ifdef INTERACTIVE
  1349. #ifndef SIGNALS
  1350.     NewEvents();
  1351. #endif
  1352.     /*Look for an event*/
  1353.     if (curEvent != lastEvent)
  1354.     {
  1355.     /*There is an event*/
  1356.     curEvent = (curEvent + 1) % MAXNEVENTS;
  1357.     readFromScript = false;
  1358.  
  1359.     knownUserEvent = false;
  1360.         switch (events[curEvent] . type)
  1361.         {
  1362.         case ET_SET_WINDOW:
  1363.         /*Changed windows, reset the moving quality to highest*/
  1364.         if (IsValidWindow(events[curEvent] . data . window))
  1365.         {
  1366.             inputWindow = events[curEvent] . data . window;
  1367.         }
  1368.         else
  1369.         {
  1370.             inputWindow = 0;
  1371.         }
  1372.         break;
  1373.         case ET_ICONIFY_WINDOW:
  1374.         /*Window has been iconified*/
  1375.         if (IsValidWindow(events[curEvent] . data . window))
  1376.         {
  1377.             events[curEvent] . data . window -> flags |= WINICONIFIED;
  1378.         }
  1379.         break;
  1380.         case ET_DEICONIFY_WINDOW:
  1381.         /*Window has been iconified*/
  1382.         if (IsValidWindow(events[curEvent] . data . window))
  1383.         {
  1384.             events[curEvent] . data . window -> flags &= ~WINICONIFIED;
  1385.         }
  1386.         break;
  1387.         case ET_DEPTHCHANGE_WINDOW:
  1388.         /*Window's depth has changed.  See if we need to 
  1389.           change any subwindow*/
  1390.         if (IsValidWindow(events[curEvent] . data . window))
  1391.         {
  1392.             WinInfoPtr superWindow;
  1393.             ObjPtr subWindows;
  1394.  
  1395.             /*See if it has subwindows and needs to be popped*/
  1396.             superWindow = (WinInfoPtr) GetVar((ObjPtr) events[curEvent] . data . window, SUPERWINDOW);
  1397.             subWindows = GetVar((ObjPtr) superWindow, SUBWINDOWS);
  1398.  
  1399.             if (subWindows && !superWindow)
  1400.             {
  1401.             /*Window has sub windows*/
  1402.             if (TopWindow() == events[curEvent] . data . window)
  1403.             {
  1404.                 /*Pop the subwindows*/
  1405.                 ThingListPtr runner;
  1406.                 runner = LISTOF(subWindows);
  1407.                 while (runner)
  1408.                 {
  1409.                 PopWindow((WinInfoPtr) runner -> thing);
  1410.                 runner = runner -> next;
  1411.                 }
  1412.             }
  1413.             else if (BottomWindow() == events[curEvent] . data . window)
  1414.             {
  1415.                 ThingListPtr runner;
  1416.                 /*This window has just been pushed*/
  1417.     
  1418.                 /*This may be a superwindow which has been pushed.
  1419.                   Check to see if all the subwindows are OK*/
  1420.                 superWindow = events[curEvent] . data . window;
  1421.                 subWindows = GetVar((ObjPtr) superWindow, SUBWINDOWS);
  1422.                 runner = LISTOF(subWindows);
  1423.                 while (runner)
  1424.                 {
  1425.                 if (!BelowAllBut((WinInfoPtr) runner -> thing, superWindow))
  1426.                 {
  1427.                     /*Window out of place*/
  1428.                     break;
  1429.                 }
  1430.                 runner = runner -> next;
  1431.                 }
  1432.  
  1433.                 if (runner)
  1434.                 {
  1435.                 /*One window is out of place.  Push subwindows*/
  1436.                 runner = LISTOF(subWindows);
  1437.                 while (runner)
  1438.                 {
  1439.                     PushWindow((WinInfoPtr) runner -> thing);
  1440.                     runner = runner -> next;
  1441.                 }
  1442.  
  1443.                 /*Push super window*/
  1444.                 PushWindow(superWindow);
  1445.                 }
  1446.             }
  1447.             }
  1448.         }
  1449.         break;
  1450.         case ET_ROTATE_DIAL:
  1451.         if (runningScript)
  1452.         {
  1453.             return;
  1454.         }
  1455.         if (inputWindow && IsValidWindow(inputWindow))
  1456.         {
  1457.             RotateDial(inputWindow,
  1458.             events[curEvent] . data . dial . whichDial,
  1459.             events[curEvent] . data . dial . delta,
  1460.             events[curEvent] . flags);
  1461.         }
  1462.         break;
  1463.         case ET_KEY_DOWN:
  1464.         if (runningScript)
  1465.         {
  1466.             AbortScriptAlert();
  1467.             return;
  1468.         }
  1469.  
  1470.         sentKey = events[curEvent] . data . key;
  1471.         keyWindow = inputWindow;
  1472.         KeyDown(events[curEvent] . data . key,
  1473.             events[curEvent] . flags);
  1474.  
  1475.         break;
  1476.         case ET_MOUSE_DOWN:
  1477.         if (runningScript)
  1478.         {
  1479.             AbortScriptAlert();
  1480.             return;
  1481.         }
  1482.         MouseDown(events[curEvent] . data . mouse . mouseButton,
  1483.             events[curEvent] . data . mouse . x,
  1484.             events[curEvent] . data . mouse . y,
  1485.             events[curEvent] . flags);
  1486.         break;
  1487.         case ET_RESHAPE_WINDOW:
  1488.         if (IsValidWindow(events[curEvent] . data . window))
  1489.         {
  1490.             ObjPtr subWindows;
  1491.             long ol, or, ob, ot, nl, nr, nb, nt;
  1492.             long sx, sy, ox, oy;
  1493.             SelWindow(events[curEvent] . data . window);
  1494.             
  1495.             if (!selWinInfo)
  1496.             {
  1497.             break;
  1498.             }
  1499.  
  1500.             reshapeviewport();
  1501.  
  1502.             /*Stuff ol, or, ob, ot*/
  1503.             getorigin(&ox, &oy);
  1504.             getsize(&sx, &sy);
  1505.  
  1506.             ol = ((WinInfoPtr) selWinInfo) -> nl;
  1507.             or = ((WinInfoPtr) selWinInfo) -> nr;
  1508.             ob = ((WinInfoPtr) selWinInfo) -> nb;
  1509.             ot = ((WinInfoPtr) selWinInfo) -> nt;
  1510.  
  1511.             nl = ox;
  1512.             nr = ox + sx;
  1513.             nb = oy;
  1514.             nt = oy + sy;
  1515.  
  1516.             if (nl != ol || nr != or || nb != ob || nt != ot)
  1517.             {
  1518.             /*Change this window*/
  1519.             ((WinInfoPtr) selWinInfo) -> ol = ol;
  1520.             ((WinInfoPtr) selWinInfo) -> or = or;
  1521.             ((WinInfoPtr) selWinInfo) -> ob = ob;
  1522.             ((WinInfoPtr) selWinInfo) -> ot = ot;
  1523.  
  1524.             ((WinInfoPtr) selWinInfo) -> nl = nl;
  1525.             ((WinInfoPtr) selWinInfo) -> nr = nr;
  1526.             ((WinInfoPtr) selWinInfo) -> nb = nb;
  1527.             ((WinInfoPtr) selWinInfo) -> nt = nt;
  1528.  
  1529.             if (logging && !GetVar((ObjPtr) selWinInfo, SUPERWINDOW) &&
  1530.                 !GetPredicate((ObjPtr) selWinInfo, INHIBITLOGGING))
  1531.             {
  1532.                 char cmd[400];
  1533.                 sprintf(cmd, "locate %d %d %d %d\n",
  1534.                 nl, nr, nb, nt);
  1535.                 Log(cmd);
  1536.             }
  1537.             ReshapeWindow((ObjPtr) selWinInfo);
  1538.             }
  1539.             /*The window has been moved.  Both buffers are bad*/
  1540.             ImInvalid((ObjPtr) selWinInfo);
  1541.  
  1542.             /*Now, see if any of the subwindows need moving*/
  1543.             subWindows = GetVar((ObjPtr) selWinInfo, SUBWINDOWS);
  1544.             if (subWindows)
  1545.             {
  1546.             long sox, soy, ssx, ssy;
  1547.             long l, r, b, t;
  1548.             ObjPtr var;
  1549.             real margin[4];
  1550.  
  1551.             ThingListPtr runner;
  1552.             runner = LISTOF(subWindows);
  1553.             while (runner)
  1554.             {
  1555.                 SelWindow((WinInfoPtr) runner -> thing);
  1556.  
  1557.                 /*Get the window position within superwindow*/
  1558.                 getorigin(&sox, &soy);
  1559.                 getsize(&ssx, &ssy);
  1560.                 var = GetVar(runner -> thing, SUBWINDOWMARGIN);
  1561.                 if (var)
  1562.                 {
  1563.                 Array2CArray(margin, var);
  1564.                 }
  1565.                 else
  1566.                 {
  1567.                 margin[0] = 0.0;
  1568.                 margin[1] = 0.0;
  1569.                 margin[2] = 0.0;
  1570.                 margin[3] = 0.0;
  1571.                 }
  1572.  
  1573.                 /*Adjust*/
  1574.                 l = nl + (int) margin[0];
  1575.                 r = nr - (int) margin[1];
  1576.                 b = nb + (int) margin[2];
  1577.                 t = nt - (int) margin[3];
  1578.  
  1579.                 if (l != sox || b != soy ||
  1580.                 r != sox + ssx - 1 || t != soy + ssy - 1)
  1581.                 {
  1582.                 winposition(l, r, b, t);
  1583.                 ImInvalid(runner -> thing);
  1584.                 }
  1585.  
  1586.                 runner = runner -> next;
  1587.             }
  1588.             }
  1589.         }
  1590.         break;
  1591.         case ET_DRAW_WINDOW:
  1592.         if (IsValidWindow(events[curEvent] . data . window))
  1593.         {
  1594.             SelWindow(events[curEvent] . data . window);
  1595.  
  1596.             reshapeviewport();
  1597.             if (selWinInfo)
  1598.             {
  1599.             /*Both buffers are bad*/
  1600.             ImInvalid((ObjPtr) selWinInfo);
  1601.             }
  1602.         }
  1603.         break;
  1604.         case ET_CLOSE_WINDOW:
  1605.         if (IsValidWindow(events[curEvent] . data . window))
  1606.         {
  1607.             CloseWindow(events[curEvent] . data . window);
  1608.         }
  1609.         break;
  1610.         case ET_QUIT:
  1611.         MaybeQuit();
  1612.         break;
  1613.     }
  1614.     }
  1615.     else
  1616. #endif
  1617.     if (settleEvents > 0)
  1618.     {
  1619.     --settleEvents;
  1620.     }
  1621.     else
  1622.     {
  1623.     struct tms buffer;
  1624.  
  1625.     if (interactiveMoving)
  1626.     {
  1627.         /*See if we've delayed long enough*/
  1628.         if (times(&buffer) - interactBegin > INTERACTDELAY)
  1629.         {
  1630.         DrawInteractive(false);
  1631.         }
  1632.     }
  1633.  
  1634.     /*If there's an object to drop, drop it.*/
  1635.     if (dropObject)
  1636.     {
  1637.         WinInfoPtr dropWindow;
  1638.  
  1639.         dropWindow = WhichWindow(dropX, dropY);
  1640.  
  1641.         if (dropWindow)
  1642.         {
  1643.         int left, right, bottom, top;
  1644.         int ox, oy;
  1645.  
  1646.         SelWindow(dropWindow);
  1647.         GetWindowBounds(&left, &right, &bottom, &top);
  1648.         GetWindowOrigin(&ox, &oy);
  1649.         dropX -= ox;
  1650.         dropY -= oy;
  1651.  
  1652.         if (dropX >= left && dropX <= right &&
  1653.             dropY >= bottom && dropY <= top)
  1654.         {
  1655.             FuncTyp method;
  1656.             /*Drop*/
  1657.             method = GetMethod((ObjPtr) selWinInfo, DROPOBJECTS);
  1658.             if (method)
  1659.             {
  1660.             if (logging)
  1661.             {
  1662.                 char cmd[256];
  1663.                 sprintf(cmd, "drop %d %d\n", dropX, dropY);
  1664.                 Log(cmd);
  1665.                 InhibitLogging(true);
  1666.             }
  1667.             
  1668.             (*method)(selWinInfo, dropObject, dropX, dropY);
  1669.             if (logging)
  1670.             {
  1671.                 InhibitLogging(false);
  1672.             }
  1673.             }
  1674.         }
  1675.         }
  1676.         DeleteThing(dropObject);
  1677.         dropObject = NULLOBJ;
  1678.     }
  1679.  
  1680. #ifdef CHANGECURSOR
  1681. #ifdef INTERACTIVE
  1682. #ifdef GRAPHICS
  1683.     {
  1684.         WinInfoPtr cursorWindow;
  1685.         FuncTyp method;
  1686.         int x, y;
  1687.  
  1688.         x = getvaluator(MOUSEX);
  1689.         y = getvaluator(MOUSEY);
  1690.         cursorWindow = WhichWindow(x, y);
  1691.         if (cursorWindow != lastCursorWindow)
  1692.         {
  1693.         /*Enter and leave messages*/
  1694.         if (lastCursorWindow)
  1695.         {
  1696.             method = GetMethod((ObjPtr) lastCursorWindow, LEAVECURSOR);
  1697.             if (method)
  1698.             {
  1699.             (*method)(lastCursorWindow);
  1700.             }
  1701.         }
  1702.         if (cursorWindow)
  1703.         {
  1704.             method = GetMethod((ObjPtr) cursorWindow, ENTERCURSOR);
  1705.             if (method)
  1706.             {
  1707.             SelWindow(cursorWindow);
  1708.             (*method)(cursorWindow);
  1709.             }
  1710.         }
  1711.         lastCursorWindow = cursorWindow;
  1712.         }
  1713.         if (cursorWindow)
  1714.         {
  1715.         method = GetMethod((ObjPtr) cursorWindow, IDLECURSOR);
  1716.         if (method)
  1717.         {
  1718.             SelWindow(cursorWindow);
  1719.             (*method)((ObjPtr) cursorWindow, x, y);
  1720.         }
  1721.         }
  1722.     }
  1723. #endif
  1724. #endif
  1725. #endif
  1726.  
  1727.     /*Idle the windows if appropriate*/
  1728.     if (settingUp && runningScript)
  1729.     {
  1730.         readFromScript = true;
  1731.         doNap = false;
  1732.     }
  1733.     else
  1734.     {
  1735.         readFromScript = IdleAllWindows() ? false : true;
  1736.         doNap = readFromScript;
  1737.     }
  1738.  
  1739.         if (readFromScript)
  1740.     {
  1741.         if (runningScript)
  1742.         {
  1743.         ReadScriptLine();
  1744.         }
  1745.         else
  1746.         {
  1747. #ifdef SOCKETS
  1748.         /*Idle all connections*/
  1749.         IdleAllConnections();
  1750. #endif
  1751.         }
  1752.     }
  1753.     IdleTimers();
  1754.  
  1755. #ifdef RELEASE
  1756.     TrashDay();
  1757. #else
  1758.     if (GetPrefTruth(PREF_RECKLESSGC))
  1759.     {
  1760.         struct tms buffer;
  1761.         long curTime;
  1762.         curTime = times(&buffer);
  1763.         if (curTime - lastGC > GCEVERY)
  1764.         {
  1765.         TrashDay();
  1766.         lastGC = curTime;
  1767.         }
  1768.     }
  1769.     else
  1770.     {
  1771.         TrashDay();
  1772.     }
  1773. #endif
  1774.     if (doNap && GetPrefTruth(PREF_NAPWHENIDLE))
  1775.     {
  1776.         struct tms buffer;
  1777.         long curTime;
  1778.         curTime = times(&buffer);
  1779.         if (curTime - lastAwake > NAPEVERY)
  1780.         {
  1781.         sleep(1);
  1782.         }
  1783.     }
  1784.     else
  1785.     {
  1786.         struct tms buffer;
  1787.         lastAwake = times(&buffer);
  1788.     }
  1789.     }
  1790. }
  1791.  
  1792. void MainLoop()
  1793. /*Main loop for scian*/
  1794. {
  1795.     SetSystemClock(0.0);
  1796.     while (running)
  1797.     {
  1798.     EndLongOperation();
  1799.     OneEvent(true);
  1800.     }
  1801.     EndScript();
  1802.     if (stereoOn)
  1803.     {
  1804. #ifdef IRISNTSC
  1805.     Set60();
  1806. #endif
  1807.     }
  1808. }
  1809.  
  1810. #ifdef PROTO
  1811. void InitEvents(void)
  1812. #else
  1813. void InitEvents()
  1814. #endif
  1815. {
  1816.     int k;
  1817.  
  1818.     for (k = 0; k < FK_N; ++k) functionKeyNames[k] = 0;
  1819.  
  1820.     functionKeyNames[FK_1 - FK_BASE] = "F1";
  1821.     functionKeyNames[FK_2 - FK_BASE] = "F2";
  1822.     functionKeyNames[FK_3 - FK_BASE] = "F3";
  1823.     functionKeyNames[FK_4 - FK_BASE] = "F4";
  1824.     functionKeyNames[FK_5 - FK_BASE] = "F5";
  1825.     functionKeyNames[FK_6 - FK_BASE] = "F6";
  1826.     functionKeyNames[FK_7 - FK_BASE] = "F7";
  1827.     functionKeyNames[FK_8 - FK_BASE] = "F8";
  1828.     functionKeyNames[FK_9 - FK_BASE] = "F9";
  1829.     functionKeyNames[FK_10 - FK_BASE] = "F10";
  1830.     functionKeyNames[FK_11 - FK_BASE] = "F11";
  1831.     functionKeyNames[FK_12 - FK_BASE] = "F12";
  1832.     functionKeyNames[FK_PRINT_SCREEN - FK_BASE] = "Print";
  1833.  
  1834.     drawLaterList = NewList();
  1835.     AddToReferenceList(drawLaterList);
  1836. }
  1837.  
  1838. #ifdef PROTO
  1839. void KillEvents(void)
  1840. #else
  1841. void KillEvents()
  1842. #endif
  1843. {
  1844.     RemoveFromReferenceList(drawLaterList);
  1845. }
  1846.